//
//  BCUserLoginManager.m
//  GSBlockChain
//
//  Created by guoshikeji_a on 2018/12/25.
//  Copyright © 2018 guoshikeji. All rights reserved.
//

#import "BCUserLoginManager.h"

#import <SAMKeychain.h>

@interface BCUserLoginManager ()

/**
 存储登录用户信息的文件path
 */
@property (nonatomic, copy) NSString *loginInfosPath;


#pragma mark - data

/**
 *所有在此设备上登录过的用户信息
 */
@property (nonatomic, strong) NSMutableArray <UserInfoModel *> *loginInfos;

@end

@implementation BCUserLoginManager

static BCUserLoginManager *_userLoginManager = nil;
+ (instancetype)sharedLogin {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!_userLoginManager) {
            _userLoginManager = [[BCUserLoginManager alloc] init];
        }
    });
    return _userLoginManager;
}
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.loginInfosPath = [self createCachaUserInfomationFile];
        //
        [self initLoginInfos];
    }
    return self;
}
/**
 创建存放登录用户信息的文件
 */
- (NSString *)createCachaUserInfomationFile {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, true);
    NSString *documentPath = paths[0];
    //创建目录
    NSFileManager *fm = [NSFileManager defaultManager];
    NSString *directoryFileName = @"F3APP";
    NSString *directoryPath = [documentPath stringByAppendingPathComponent:directoryFileName];
    if (![fm fileExistsAtPath:directoryPath]) {
        [fm createDirectoryAtPath:directoryPath withIntermediateDirectories:false attributes:nil error:nil];
    }
    //创建文件
    NSString *userInfoFileName = @"LoginInfos";
    NSString *directoryUserInfos = [directoryPath stringByAppendingPathComponent:userInfoFileName];
    if (![fm fileExistsAtPath:directoryUserInfos]) {
        [fm createFileAtPath:directoryUserInfos contents:nil attributes:nil];
    }else {
        NSLog(@"已经创建!!!");
    }
    return directoryUserInfos;
}

#pragma mark - 初始化获取当前设备上登录的用户信息
- (void)initLoginInfos {
    self.loginInfos = [NSMutableArray array];
    //
    NSArray *localArr = [NSArray arrayWithContentsOfFile:self.loginInfosPath];
    if (localArr) {
        for (int i=0; i<localArr.count; i++) {
            id obj = localArr[i];
            UserInfoModel *userInfo = [UserInfoModel yy_modelWithJSON:obj];
            if (userInfo) {
                [self.loginInfos addObject:userInfo];
            }
        }
    }
}
/**
 更新最新的登录用户数据到文件
 */
- (void)updateLoginInfosToFile {
    if (self.loginInfos.count) {
        NSMutableArray *dataArr = [NSMutableArray arrayWithCapacity:self.loginInfos.count];
        for (int i=0; i<self.loginInfos.count; i++) {
            UserInfoModel *user = self.loginInfos[i];
            id obj = [user yy_modelToJSONData];//转成data形式存入
            if (obj) {
                [dataArr addObject:obj];
            }
        }
        [dataArr writeToFile:self.loginInfosPath atomically:true];
    }
}


#pragma mark - actions
/**
 更新最后登录用户到loginInfos
 */
- (void)updateLastLoginUserToInfos:(UserInfoModel *)userInfo {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        if (userInfo) {
            //先清除之前存在的user ID相同的
            NSMutableArray *temp = [NSMutableArray array];
            for (int i=0; i<self.loginInfos.count; i++) {
                UserInfoModel *user = self.loginInfos[i];
                if ([userInfo.sub isEqualToString:user.sub]) {
                    [temp addObject:user];
                }
            }
            //清除
            @try {
                for (int i=0; i<temp.count; i++) {
                    UserInfoModel *user = temp[i];
                    [self.loginInfos removeObject:user];
                }
            } @catch (NSException *exception) {
                NSLog(@"%@",exception);
            } @finally {
                
            }
            //添加新的到最后
            [self.loginInfos addObject:userInfo];
            //update
            [self updateLoginInfosToFile];
        }
    });
}


#pragma mark - 一些需要用来用户操作的数据
/**
 *userInfo 最近一次登录成功的用户信息
 */
- (UserInfoModel *)lastUserInfo {
    if (self.loginInfos.count) {
        return self.loginInfos.lastObject;
    }
    return nil;
}
/**
 *loginedUserInfos 当前所有登录过的用户信息
 */
- (NSArray<UserInfoModel *> *)loginedUserInfos {
    return self.loginInfos;
}


#pragma mark - 指纹登录或者面容登录处理 都需要与user对应
/**
 获取指纹或面容设置的登录码关联的账户
 */
- (NSString *)localAuthenticationAccount:(NSString *)userId {
    NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
    return [NSString stringWithFormat:@"%@_%@",bundleId,userId];
}
/**
 * !@brief 随机获取一个用户指纹或面容登录码 以供保存 不要传入空值
 * @param userId 用户id
 * @param password 用户在设置登录码时输入的登录密码
 * @return 一个新的登录码 在服务器设置成功后保存到keyChain中就算卸载重装也不会重置
 */
- (NSString *)userInitLocalAuthenticationCode:(NSString *)userId password:(NSString *)password {
    /**
     方式：用户id+用户登录密码+随机UUID -> MD5 一次
     */
    NSString *uid = userId;
    NSString *passW = password;
    NSString *uuid = [NSUUID UUID].UUIDString;
    uuid = [uuid stringByReplacingOccurrencesOfString:@"-" withString:@""];
    NSString *code = [NSString stringWithFormat:@"%@%@%@",uid,passW,uuid];
    return [code qmui_md5];
}
/**
 * !@brief 获取当前用户关联指纹或面容登录码
 * @param userId 用户
 * @return 当前用户的登录码 nil 则还未开启
 */
- (NSString *)getCurrentUserLoacalAuthenticationCode:(NSString *)userId {
    NSString *currentAccount = [self localAuthenticationAccount:userId];
    @try {
        NSString *code = [SAMKeychain passwordForService:SAMKeychainService account:currentAccount];
        return code;
    } @catch (NSException *exception) {
        NSLog(@"\n\n\n%@\n\n\n\n",exception);
    } @finally {}
    return nil;
}
/**
 * !@brief 删除当前用户关联指纹或面容登录码
 * @param userId 用户
 * @return 当前用户的登录码是否删除
 */
- (BOOL)deleteCurrentUserLocalAuthticationCode:(NSString *)userId {
    NSString *currentAccount = [self localAuthenticationAccount:userId];
    @try {
        BOOL delete = [SAMKeychain deletePasswordForService:SAMKeychainService account:currentAccount error:nil];
        return delete;
    } @catch (NSException *exception) {
        NSLog(@"\n\n\n%@\n\n\n\n",exception);
    } @finally {}
    return false;
}

/**
 * !@brief 给用户设置一个登录码进keychain
 * @param code 登录码
 * @param userId 用户
 * @param error 如果设置发生错误 返回
 * @return 是否成功
 */
- (BOOL)setCurrentUserLoacalAuthenticationCode:(NSString *)code userId:(NSString *)userId error:(NSError **)error {
    if (!code.length) {
        *error = [NSError errorWithDomain:@"Code can not be Null!!!" code:0 userInfo:nil];
        return false;
    }
    if (!userId.length) {
        *error = [NSError errorWithDomain:@"UserId can not be Null!!!" code:0 userInfo:nil];
        return false;
    }
    NSString *account = [self localAuthenticationAccount:userId];
    NSString *service = SAMKeychainService;
    //设置之前尝试删除一下以前的
    @try {
        [SAMKeychain deletePasswordForService:service account:account];
    } @catch (NSException *exception) {} @finally {}
    //
    NSError *samError;
    BOOL success = [SAMKeychain setPassword:code forService:service account:account error:&samError];
    if (samError&&error) {
        *error = samError;
    }
    return success;
}

//
- (BOOL)isOpenLocalAuthenticationWithUserId:(NSString *)userId {
    if (userId.length) {
        NSString *code = [self getCurrentUserLoacalAuthenticationCode:userId];
        return code==nil?false:true;
    }
    return false;
}

@end
